package com.lyon.custom.core;

import com.lyon.custom.config.LyonConfigProperties;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;

import java.util.List;

/**
 * 自定义加载外部环境到spring env
 *
 * @author LeeYan9
 * @since 2021-11-26
 */
public class LyonPropertySourceLocator implements PropertySourceLocator {

    LyonConfigManager lyonConfigManager;

    ConfigService configService;

    LyonPropertySourceBuilder lyonPropertySourceBuilder;

    LyonConfigProperties configProp;

    public LyonPropertySourceLocator(LyonConfigManager lyonConfigManager, LyonConfigProperties configProp) {
        this.lyonConfigManager = lyonConfigManager;
        this.configService = lyonConfigManager.getConfigService();
        this.configProp = configProp;
        this.lyonPropertySourceBuilder = new LyonPropertySourceBuilder(configService);
    }

    @Override
    public PropertySource<?> locate(Environment environment) {
        // 创建一个 avatar 复合属性源
        CompositePropertySource composite = new CompositePropertySource("AVATAR-CUSTOM-CONFIG");
        // 加载共享配置;
        loadSharedConfig(composite);
        // 加载扩展配置;
        loadExtConfig(composite);
        // 加载应用配置;
        loadApplicationConfig(composite, environment);
        return composite;
    }

    private void loadExtConfig(CompositePropertySource composite) {
        List<LyonConfigProperties.ConfigOuterProperties> extConfig = configProp.getExtConfig();
        if (extConfig != null) {
            for (LyonConfigProperties.ConfigOuterProperties prop : extConfig) {
                loadConfigDataIfPresent(composite, prop.getDataId(), prop.getGroup(), prop.getFileExtension());
            }
        }
    }

    private void loadSharedConfig(CompositePropertySource composite) {
        List<LyonConfigProperties.ConfigOuterProperties> sharedConfig = configProp.getSharedConfigs();
        if (sharedConfig != null) {
            for (LyonConfigProperties.ConfigOuterProperties prop : sharedConfig) {
                loadConfigDataIfPresent(composite, prop.getDataId(), prop.getGroup(), prop.getFileExtension());
            }
        }
    }

    private void loadApplicationConfig(CompositePropertySource composite, Environment env) {
        String dataId = configProp.getDataId();
        String group = configProp.getGroup();
        String fileExt = configProp.getFileExtension();

        // 优先级加载
        // 加载 applicaiton
        loadConfigDataIfPresent(composite, dataId, group, fileExt);
        // 加载 applicaiton.yaml
        loadConfigDataIfPresent(composite, dataId + "." + fileExt, group, fileExt);
        // 加载 applicaiton-local.yml
        for (String activeProfile : env.getActiveProfiles()) {
            loadConfigDataIfPresent(composite, dataId + "-" + activeProfile, group, fileExt);
            loadConfigDataIfPresent(composite, dataId + "-" + activeProfile + "." + fileExt, group, fileExt);
        }
    }

    private void loadConfigDataIfPresent(CompositePropertySource composite, String dataId, String group, String fileExt) {
        // 加载配置数据, 封装到 Spring PropertySource;
        LyonPropertySource lyonPropertySource = lyonPropertySourceBuilder.build(dataId, group, fileExt);
        addFirstPropertySource(composite, lyonPropertySource);
    }

    /**
     * 添加到 Spring CompositePropertySource;
     *
     * @param composite          提供的组合属性源
     * @param lyonPropertySource 属性源
     */
    private void addFirstPropertySource(CompositePropertySource composite, LyonPropertySource lyonPropertySource) {
        composite.addFirstPropertySource(lyonPropertySource);
    }
}
